using System;
using System.Collections.Generic;
using FlatRedBall;
using FlatRedBall.Math.Geometry;
using Microsoft.Devices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Xzipit.GameObjects;
using Xzipit.MenuObjects;
using Xzipit.Utilities;
using FlatRedBall.Graphics;
using Xzipit.Utilities.Gestures;
using Xzipit.Utilities.Touch;

namespace Xzipit.Screens
{
    public class GameScreen : Screen
    {
        private enum GameState
        {
            Idle,
            Playing,
            Paused,
            Restarting,
            Won
        }

        private GameState _state;

        private Level _level;
        private WinBox _winbox;
        private TimeBox _timebox;

        //private Sprite _background;
        private Text _jamText;
        private PauseBox _pauseBox;

        private RestartButton _restartButton;
        private PauseButton _pauseButton;

        private double _elapsedTime;
        private double _timeStamp;
        private double _firstTouchTime;

        private bool _clockActive;

        private bool _fadingIn;
        private bool _fadingOut;

        private bool _menuFade;
        private bool _nextFade;

        private bool _hasWon;

        #region Methods

        #region Constructor and Initialize

        public GameScreen() : base("GameScreen")
        {
            // Don't put initialization code here, do it in
            // the Initialize method below
            //   |   |   |   |   |   |   |   |   |   |   |
            //   |   |   |   |   |   |   |   |   |   |   |
            //   V   V   V   V   V   V   V   V   V   V   V

        }

        public override void Initialize(bool addToManagers)
        {
            //LevelManager.LoadLevel();

            // level and world number are stored in the game properties.
            _level = new Level();

            _winbox = new WinBox("Global");
            _timebox = new TimeBox("Global");
            _pauseButton = new PauseButton("Global");
            _restartButton = new RestartButton("Global");

            _state = GameState.Idle;

			if(addToManagers)
			{
				AddToManagers();
			}

            _clockActive = false;
            _fadingIn = false;
            _fadingOut = false;
            _hasWon = false;
            _elapsedTime = 0.0f;
        }

		public override void AddToManagers()
        {
            string contentManagerName = "Global";
            // Change the font to a custom font from dafont.

            //_background = LevelManager.Background;

            _jamText = TextManager.AddText("JAMMED!", GameProperties.CustomFont);
            _jamText.Visible = false;
            _jamText.Scale = 2.3f;
            _jamText.Spacing = 2.4f;
            _jamText.SetColor(0.0f, 0.0f, 0.0f);
            _jamText.X = -_jamText.HorizontalCenter;
            _jamText.Z = 0.5f;

            _winbox.Z = 0.6f;
            _timebox.Z = .2f;
            _timebox.X = 5.5f;
            _timebox.Y = 15.2f;

            _pauseButton.X = -8.0f;
            _pauseButton.Y = 15.0f;

            _restartButton.X = -4.5f;
            _restartButton.Y = 15.3f;

            _pauseBox = new PauseBox("Global");
            _pauseBox.Alpha = 0.0f;
            _pauseBox.Z = 0.6f;
            _pauseBox.Y = 7.0f;
		} 

        #endregion

        #region Public Methods

        public override void Activity(bool firstTimeCalled)
        {
            base.Activity(firstTimeCalled);

            if (!firstTimeCalled)
            {
                GameGestureManager.Update();
                //if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed
                //    && _state != GameState.Paused)
                //{
                //    _winbox.Visible = false;
                //    FlatRedBall.Instructions.InstructionManager.UnpauseEngine();
                //    this.Move(typeof(Screens.LevelSelectScreen).FullName);
                //}

                if (_state == GameState.Restarting)
                {
                    if ((TimeManager.CurrentTime - _timeStamp > 1.0f)
                        && _level.DoneFading())
                    {
                        FlatRedBall.Instructions.InstructionManager.UnpauseEngine();
                        _winbox.Visible = false;
                        _level.Destroy();
                        this.Move(typeof(Screens.GameScreen).FullName);
                    }
                }
                else if (_fadingIn || _state == GameState.Idle)
                {
                    FadeIn();
                    _state = GameState.Playing;
                }
                else if (_fadingOut)
                {
                    FadeOut();
                }
                else if (_winbox.ToMenu)
                {
                    if (!_menuFade)
                    {
                        _winbox.FadeOut();
                        FlatRedBall.Instructions.InstructionManager.UnpauseEngine();

                        FadeOut();

                        _menuFade = true;
                    }
                    else
                    {
                        this.Move(typeof(Screens.LevelSelectScreen).FullName);
                    }
                }
                else if (_winbox.ToWorld)
                {
                    if (!_menuFade)
                    {
                        _winbox.FadeOut();
                        FlatRedBall.Instructions.InstructionManager.UnpauseEngine();

                        FadeOut();

                        _menuFade = true;
                    }
                    else
                    {
                        this.Move(typeof(Screens.WorldSelectScreen).FullName);
                    }
                }
                else if (_winbox.ToNext)
                {
                    if (!_nextFade)
                    {
                        _winbox.FadeOut();
                        FlatRedBall.Instructions.InstructionManager.UnpauseEngine();

                        FadeOut();

                        _nextFade = true;
                    }
                    else
                    {
                        GameProperties.SelectedLevel++;
                        Reset();
                    }
                }
                else if (_state == GameState.Won)
                {
                    _winbox.Activity();
                    CheckRestart();
                }
                else if (_hasWon)
                {
                    // the level in the game, disregarding what world.
                    int rawLevel = (GameProperties.LEVELS_PER_WORLD * (GameProperties.SelectedWorld - 1))
                                 + GameProperties.SelectedLevel;
                    if (GameProperties.Save.TotalPoints < rawLevel)
                    {
                        GameProperties.Save.TotalPoints++;
                    }

                    _timebox.Activity(_elapsedTime, _level.TargetTimes);
                    _winbox.Activity();
                    _winbox.Display(_elapsedTime, _level.TargetTimes);
                    StopObstacles();
                    CheckRestart();

                    _state = GameState.Won;
                }
                else if (_state == GameState.Paused)
                {
                    _pauseBox.Activity();
                    if (_pauseBox.Resume)
                    {
                        TogglePause();
                    }
                    else if (_pauseBox.Menu)
                    {
                        FlatRedBall.Instructions.InstructionManager.UnpauseEngine();
                        this.Move(typeof(Screens.LevelSelectScreen).FullName);
                    }
                    else if (_pauseBox.Exit)
                    {
                        GameProperties.ExitGame = true;
                    }
                    CheckPause();
                }
                else
                {
                    

                    // Removes the jam text if the zipper is no longer jammed.
                    if (_level.IsZipperJammed)
                    {
                        FlashJammedText();
                    }
                    else// if (_zipper.State == Zipper.ZipperState.Jammed && _jammed.Visible)
                    {
                        _jamText.Visible = false;
                    }

                    _level.Activity(_elapsedTime);
                    _hasWon = _level.HasWon;

                    if (_clockActive)
                    {
                        _elapsedTime += (TimeManager.CurrentTime - _timeStamp);
                        _timebox.Activity(_elapsedTime, _level.TargetTimes);
                    }
                    else if (!_clockActive)
                    {
                        if (GestureDetected())
                        {
                            _clockActive = true;
                            _timeStamp = TimeManager.CurrentTime;
                        }
                    }

                    _timeStamp = TimeManager.CurrentTime;

                    CheckPause();
                    CheckRestart();
                }
            }
            else
            {
                _firstTouchTime = TimeManager.CurrentTime;
            }
        }

        public override void Destroy()
        {
            base.Destroy();
            _level.Destroy();
            _winbox.Destroy();
            _timebox.Destroy();
            _pauseButton.Destroy();
            _restartButton.Destroy();
            _pauseBox.Destroy();

            TextManager.RemoveText(_jamText);
        }

        private void StopObstacles()
        {
            _level.Stop();
        }

        private void Reset()
        {
            _state = GameState.Restarting;
            _elapsedTime = 0.0f;

            _level.FadeOut();

            _hasWon = false;
            _firstTouchTime = TimeManager.CurrentTime;

            _winbox.Reset();
            _level.Reset();
            _timebox.Reset();
        }

        private bool GestureDetected()
        {
            foreach (GameGesture g in GameGestureManager.Gestures)
            {
                if (g.StartTime > _firstTouchTime)
                {
                    return true;
                }
            }

            return false;
        }

        #endregion

        #region Collision Detection

        private void CheckRestart()
        {
            if (_restartButton.Collide())
            {
                _hasWon = false;
                _winbox.Visible = false;

                Reset();
            }
        }

        private void CheckPause()
        {
            if (_pauseButton.Collide()
             || (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed))
                //&& _state == GameState.Paused))
            {
                TogglePause();
            }
        }

        private void TogglePause()
        {
            if (_state != GameState.Paused)
            {
                _state = GameState.Paused;
                _timebox.FlipPausedState();

                FlatRedBall.Instructions.InstructionManager.PauseEngine();
                _pauseBox.FadeIn();
            }
            else
            {
                _state = GameState.Playing;
                _timebox.FlipPausedState();

                _timeStamp = TimeManager.CurrentTime;
                _firstTouchTime = TimeManager.CurrentTime;
                _clockActive = false;

                FlatRedBall.Instructions.InstructionManager.UnpauseEngine();
                _pauseBox.FadeOut();
                _pauseBox.Reset();
            }
        }

        #endregion

        private void FlashJammedText()
        {
            _jamText.Visible = true;

            // flashes the jam text
            if (_jamText.Alpha == 0.0f)
            {
                _jamText.AlphaRate = 1.5f;
            }
            else if (_jamText.Alpha == 1.0f)
            {
                _jamText.AlphaRate = -6.5f;
            }
        }

        #region Fading
        private void FadeIn()
        {
            if (!_fadingIn)
            {
                _level.FadeIn();
                _fadingIn = true;
            }
            else if (_level.DoneFading() || GestureDetected())
            {
                _fadingIn = false;

                _clockActive = false;

                _level.QuickFadeIn();
            }
        }

        private void FadeOut()
        {
            if (!_fadingOut)
            {
                _level.FadeOut();
                _fadingOut = true;
            }
            else if (_level.DoneFading())
            {
                _fadingOut = false;
            }
        }

        #endregion

        #endregion
    }
}

